package com.drelephant.commons.util;


import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

/**
 * AES 加密工具
 *
 * @author wenshuai@hz-health.cn
 */
public class AESUtils {

    /**
     * AES解密
     */
    public static String decrypt(String base64Key, String base64CipherText, String base64Iv) throws Exception {
        SecretKeySpec keySpec = new SecretKeySpec(Base64.getDecoder().decode(base64Key), "AES");
        Cipher cipher = Cipher.getInstance("AES/CFB/PKCS5Padding");
        IvParameterSpec iv = new IvParameterSpec(Base64.getDecoder().decode(base64Iv));
        cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);
        byte[] original = cipher.doFinal(Base64.getDecoder().decode(base64CipherText));
        return new String(original, StandardCharsets.UTF_8);
    }

    /**
     * AES加密
     *
     * @param data 待加密字符串
     * @return 加密结果
     * @throws Exception 加密异常
     */
    public static EncryptResult encrypt(String data) throws Exception {
        // 生成AES加密的Key
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        keyGenerator.init(128);
        SecretKey secretKey = keyGenerator.generateKey();
        byte[] enCodeFormat = secretKey.getEncoded();
        SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
        // 指定偏移量
        String ivParameter = "1234567890123456";
        IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes());
        // 创建AES加密编码器
        Cipher cipher = Cipher.getInstance("AES/CFB/PKCS5Padding");
        // 初始化AES加密
        cipher.init(Cipher.ENCRYPT_MODE, key, iv);
        // 进行AES加密
        byte[] byteContent = data.getBytes(StandardCharsets.UTF_8);
        byte[] result = cipher.doFinal(byteContent);
        // AES加密结果Base64Encode
        EncryptResult encryptResult = new EncryptResult();
        encryptResult.setKey(Base64.getEncoder().encodeToString(key.getEncoded()));
        encryptResult.setSalt(Base64.getEncoder().encodeToString(iv.getIV()));
        encryptResult.setCipherText(Base64.getEncoder().encodeToString(result));
        return encryptResult;
    }

    /**
     * 加密结果  包含key salt cipherText
     */
    public static class EncryptResult {

        private String key;

        private String salt;

        private String cipherText;

        public String getKey() {
            return key;
        }

        public void setKey(String key) {
            this.key = key;
        }

        public String getSalt() {
            return salt;
        }

        public void setSalt(String salt) {
            this.salt = salt;
        }

        public String getCipherText() {
            return cipherText;
        }

        public void setCipherText(String cipherText) {
            this.cipherText = cipherText;
        }
    }
}